package com.dx.mes.service.query.service;

import com.dx.common.table.his.His_ret_tool_st;
import com.dx.common.table.ppt.Bis_tool;
import com.dx.common.table.ppt.Bis_tool_gr;
import com.dx.mes.common.dao.IBisToolDao;
import com.dx.mes.common.dao.IBisToolGrDao;
import com.dx.mes.common.dao.IHisRetToolStDao;
import com.dx.mes.common.dao.IRetToolStDao;
import com.dx.mes.common.transcoder.util.AppContext;
import com.dx.mes.common.transcoder.util.JacksonUtil;
import com.dx.mes.common.transcoder.util.LogUtils;
import com.dx.mes.common.transcoder.util.Util;
import com.dx.mes.facade.query.service.IFipinqtoolService;
import com.dx.mes.facade.query.tx.Fipinqtool.*;
import com.dx.mes.facade.query.tx.Hiptolhis.HiptolhisI;
import com.dx.mes.facade.query.tx.Hiptolhis.HiptolhisIA;
import com.dx.mes.facade.query.tx.Hiptolhis.HiptolhisO;
import com.dx.mes.facade.query.tx.Hiptolhis.HiptolhisOA;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.dx.mes.common.bean.def.GenericDef.*;

/**
 * Created by cmj on 2017/11/18.
 */
@Service("fipinqtoolService")
public class FipinqtoolService implements IFipinqtoolService {
    private LogUtils logUtils;
    private static final String TX_NAME = "FIPINQTOL";
//    @Resource
//    private SessionFactory sessionFactoryHis;

    @Autowired
	private IBisToolDao bisToolDao;

    @Autowired
    private IRetToolStDao retToolStDao;

    @Autowired
	private IHisRetToolStDao hisRetToolStDao;

    @Autowired
    private IBisToolGrDao bisToolGrDao;
//	@Autowired
//	private IHisRetToolPtDao hisRetToolPtDao;

	@Override
    public String subMainProc(String evt_no, String strInMsg) {
        AppContext.clear();
        AppContext.setCurrServiceName(FipinqtoolService.class.getSimpleName());
        AppContext.setCurrEventNumber(evt_no);
        logUtils = new LogUtils(FipinqtoolService.class);
        logUtils.info("[InTrx:" + strInMsg + "]");
//        Session session = sessionFactoryHis.getCurrentSession();
        String outMsg = "";

        FipinqtoolI inTrx = new FipinqtoolI();
        FipinqtoolO outTrx = new FipinqtoolO();

        outTrx.setTrx_id(TX_NAME);
        outTrx.setType_id(TRX_OUT);
        outTrx.setRtn_code(String.valueOf(RETURN_CODE_SET_ERROR));

        try {
            inTrx = JacksonUtil.fromJson(strInMsg, FipinqtoolI.class);
            subMainProc2(inTrx.getAction_flg().toCharArray()[0],inTrx,outTrx);
            ;
            if (RETURN_CODE_OK.equals(outTrx.getRtn_code())) {
//                session.flush();
            } else {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            }
        } catch (Exception ex) {
            outTrx.setRtn_mesg(ex.toString());
            outTrx.setRtn_code(RETURN_CODE_UNKNOWN);
            logUtils.error(Util.stackTraceToString(ex));
        } finally {
            outMsg = JacksonUtil.toJSONStr(outTrx);
            logUtils.info("[OutTrx:" + outMsg + "]");
        }
        return outMsg;
    }
    private void subMainProc2(char actionType, FipinqtoolI inTrx, FipinqtoolO outTrx) {

        switch (actionType) {
//            case 'T': {
//                getHisToolByCondition(inTrx,outTrx);
//                break;
//            }
            case 'O':{
                oneDayStatus(inTrx,outTrx);
                break;
            }
            case 'F':{
                fiveDayStatus(inTrx,outTrx);
                break;
            }
            default: {
                String gszMsgBuf = "Invalide type input: [" + actionType + "]";
                outTrx.setRtn_mesg(gszMsgBuf);
                outTrx.setRtn_code(String.valueOf(E_FIPINQBOX_INVALID_INPUT));
            }
        }
    }


    //获取工时
    public List<FipinqtoolOB> getToolDiffStatePeriod(FipinqtoolI inTrx){
        //1.查询条件  : 厂别，线别，站点，设备组代码（和站点绑定)，设备代码，时间段
        //2.返回结果  :  工时饼图 DOWN,IDLE,PM,RUN,STOP 各状态时间 / 筛选时间段时间
        List<FipinqtoolOB> oaryBList = new ArrayList<>();
        //当天0点
        Calendar dateTime = Calendar.getInstance();
        SimpleDateFormat temp_zero = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
        String timestamp_zero = temp_zero.format(dateTime.getTime());
        Timestamp timeStampZero = Timestamp.valueOf(timestamp_zero);
        //当前时间
        Timestamp currentTimestamp = Util.getCurrentTimestamp();
        FipinqtoolIA iary = new FipinqtoolIA();
        List<FipinqtoolIA> iaryList = inTrx.getIary();
        if(iaryList != null && iaryList.size() > 0){
            iary = iaryList.get(0);
        }
        String tool_id = iary.getTool_id();
//        String fab_id = iary.getFab_id();
        String fab_id = "102B";
        Timestamp fromDate = iary.getFrom_date();
        Timestamp toDate = iary.getTo_date();
        if(fromDate != null){
            timeStampZero = fromDate;
        }
        if(toDate != null){
            currentTimestamp = toDate;
        }
        //总间隔分钟数
        Long totalMinute = Util.getDiffMin(timeStampZero,currentTimestamp);

        String hqltoolId = "";
        if(!StringUtils.isEmpty(fab_id)){
            String toolHql = "From Bis_tool where fab_id_fk = '" + fab_id + "'";
            List<Bis_tool>  bisToolList = bisToolDao.find(toolHql);
            String str1 = "";
            if(bisToolList != null && bisToolList.size() > 0){
                for(int i = 0; i < bisToolList.size() - 1; i++){
                    str1 += "'" + bisToolList.get(i).getTool_id() +"',";
                }
                str1 += "'" + bisToolList.get(bisToolList.size() - 1).getTool_id() + "'";
            }
            hqltoolId = " and tool_id_fk in(" + str1 + ")";
        }

        String hql = "From His_ret_tool_st where 1 = 1";
        if(!StringUtils.isEmpty(tool_id)){
            hql += " and tool_id_fk = '" + tool_id + "'";
        }else if(!StringUtils.isEmpty(fab_id) && !StringUtils.isEmpty(hqltoolId)){
            hql += hqltoolId;
        }

        if (timeStampZero != null && currentTimestamp != null) {
            hql = hql +" and (clm_timestamp between '" +
                    timeStampZero +"' and '"+ currentTimestamp+"')";
        } else if (timeStampZero != null && currentTimestamp == null) {
            hql = hql +" and (clm_timestamp >='" + timeStampZero +"')";
        } else if (timeStampZero == null && currentTimestamp != null) {
            hql = hql +" and (clm_timestamp <='" + currentTimestamp +"')";
        }
        hql += " order by clm_timestamp";

        List<His_ret_tool_st>  hisRetToolStList = hisRetToolStDao.find(hql);
        if(hisRetToolStList != null && hisRetToolStList.size() > 0){
            //设备ID + 设备状态历史记录
            Map<String,List<His_ret_tool_st>> hisRetToolStMap = new HashMap<>();
            for(int i = 0 ; i < hisRetToolStList.size(); i++){
                His_ret_tool_st hisRetToolSt = hisRetToolStList.get(i);
                String toolIdFk  = hisRetToolSt.getTool_id_fk();
                if(hisRetToolStMap.containsKey(toolIdFk)){
                    hisRetToolStMap.get(toolIdFk).add(hisRetToolSt);
                }else{
                    List<His_ret_tool_st> list = new ArrayList<His_ret_tool_st>();
                    list.add(hisRetToolSt);
                    hisRetToolStMap.put(toolIdFk,list);
                }
            }

            //设备 :状态 时间
            Map<String,Map<String,ToolClmBo>> toolStatusPeriod = new HashMap<>();
            Iterator iter = hisRetToolStMap.entrySet().iterator();
            while (iter.hasNext()) {
                Map.Entry entry = (Map.Entry) iter.next(); // 把hashmap转成Iterator再迭代到entry
                Object key = entry.getKey(); // 从entry获取key 设备ID
                Object val = entry.getValue(); // 从entry获取value 设备

                String toolId = (String) key;
                List<His_ret_tool_st> tooldataList = (ArrayList<His_ret_tool_st>) val;
                //获取最后一个状态，为计算最后一次状态至当前状态做准备
                His_ret_tool_st lastHisRetToolSt = tooldataList.get(tooldataList.size()-1);
                String lastToolStat = lastHisRetToolSt.getTool_stat();
                //获取第一个状态
                String firstToolStat = tooldataList.get(0).getTool_stat();
                //状态 + bo
                Map<String,ToolClmBo> statusTimePeriod = new HashMap<>();
                for(int i = 0 ; i < tooldataList.size(); i++){
                    His_ret_tool_st hisRetToolSt = tooldataList.get(i);
                    String toolStat = hisRetToolSt.getTool_stat();
                    //持续分钟数
                    long time = Util.getDiffMin(hisRetToolSt.getPv_clm_timestamp(),hisRetToolSt.getClm_timestamp());

                     if(statusTimePeriod.containsKey(toolStat)){
                        long newTime = time + statusTimePeriod.get(toolStat).getTime();
                         ToolClmBo toolClmBo = new ToolClmBo();
                         toolClmBo.setClm_timestamp(hisRetToolSt.getClm_timestamp());
                         toolClmBo.setTime(newTime);
                         toolClmBo.setStatus(toolStat);
                         if(toolStat.equals(lastToolStat)){
                             toolClmBo.setLastStatus(true);
                         }
                        statusTimePeriod.put(toolStat,toolClmBo);
                    }else{
                         //第一次的状态从0点开始
                         Long firstTime;
                         if(firstToolStat.equals(toolStat)){
                             firstTime = Util.getDiffMin(timeStampZero,hisRetToolSt.getClm_timestamp());
                         }else{
                             firstTime = time;
                         }
                         ToolClmBo toolClmBo = new ToolClmBo();
                         toolClmBo.setClm_timestamp(hisRetToolSt.getClm_timestamp());
                         toolClmBo.setTime(firstTime);
                         toolClmBo.setStatus(toolStat);
                         if(toolStat.equals(lastToolStat)){
                             toolClmBo.setLastStatus(true);
                         }
                         statusTimePeriod.put(toolStat,toolClmBo);
                    }
                }

                toolStatusPeriod.put(toolId,statusTimePeriod);
            }

            int toolIds = toolStatusPeriod.size();
            Iterator iter2 = toolStatusPeriod.entrySet().iterator();
            while (iter2.hasNext()) {
                Map.Entry entry = (Map.Entry) iter2.next(); // 把hashmap转成Iterator再迭代到entry
                Object key = entry.getKey(); // 从entry获取key 设备ID
                Object val = entry.getValue(); // 从entry获取value 设备状态和时间

                String toolId = (String) key;
                //设备组
                String toolGrhql = "From Bis_tool_gr where tool_id_fk = '" + toolId +"'";
                List<Bis_tool_gr> bisToolGrList = bisToolGrDao.find(toolGrhql);
                String toolGrId = "";
                if(bisToolGrList !=null && bisToolGrList.size() > 0){
                    toolGrId = bisToolGrList.get(0).getId().getToolg_id();
                }
                Map<String,ToolClmBo> toolStatus = (Map<String,ToolClmBo>) val;
                Iterator iter3 = toolStatus.entrySet().iterator();
                while (iter3.hasNext()) {
                    FipinqtoolOB oaryB = new FipinqtoolOB();
                    Map.Entry entry3 = (Map.Entry) iter3.next(); // 把hashmap转成Iterator再迭代到entry
                    Object key3 = entry3.getKey(); // 从entry获取key 设备ID
                    Object val3 = entry3.getValue(); // 从entry获取value 设备状态和时间

                    String toolStatus3 = (String) key3;
                    ToolClmBo timeclmBo = (ToolClmBo) val3;
                    if(timeclmBo.isLastStatus()){
                        //最后一次的状态上报时间 截至 至当前时间
                        Long lastTime = Util.getDiffMin(timeclmBo.getClm_timestamp(),currentTimestamp);
                        timeclmBo.setTime(timeclmBo.getTime()+lastTime);
                    }

                    oaryB.setTool_id_fk(toolId);
                    oaryB.setTime(timeclmBo.getTime());
                    oaryB.setTool_stat(toolStatus3);
                    oaryB.setTimeToal(totalMinute);
                    oaryB.setToolg_id(toolGrId);
                    oaryB.setToolIds(toolIds);
                    oaryBList.add(oaryB);
                }
            }
        }
        return oaryBList;
    }

    //当天的工时分布
    public void  oneDayStatus(FipinqtoolI inTrx,FipinqtoolO outTrx) {
        List<FipinqtoolOB> oaryBList = getToolDiffStatePeriod(inTrx);
        List<FipinqtoolOC> oaryCList = makeOaryC(oaryBList);
        outTrx.setOaryB(oaryBList);
        outTrx.setOaryC(oaryCList);
        outTrx.setRtn_code(RETURN_CODE_OK);
        outTrx.setRtn_mesg(RETURN_MESG_OK);
    }

    public List<FipinqtoolOC> makeOaryC(List<FipinqtoolOB> oaryBList){
        //状态 时间
        Map<String,Long> statusMap = new HashMap<>();
        //上报状态的总时间 N个机台
//        Long statusTotalTime = null ;
        for(int i = 0; i < oaryBList.size(); i++){
            String toolStatus = oaryBList.get(i).getTool_stat();
            Long time = oaryBList.get(i).getTime();
//            statusTotalTime += time;
            if(statusMap.containsKey(toolStatus)){
                Long newTime = statusMap.get(toolStatus) + time;
                statusMap.put(toolStatus,newTime);
            }else{
                statusMap.put(toolStatus,time);
            }
        }
        //设备数量
        int toolIds = oaryBList.get(0).getToolIds();
        //一天到当前的时间（当天）  //整一天的时间（5天）
        Long timeToal = oaryBList.get(0).getTimeToal();
        Long wholeTime  = toolIds * timeToal;
//        statusMap.put("OTHER",wholeTime - statusTotalTime);

        List<FipinqtoolOC> oaryCList = new ArrayList<>();
        Iterator iter = statusMap.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next(); // 把hashmap转成Iterator再迭代到entry
            Object key = entry.getKey(); // 从entry获取key 设备ID
            Object val = entry.getValue(); // 从entry获取value 设备状态和时间

            String status = (String)key;
            Long time = (Long)val;
            FipinqtoolOC oaryC = new FipinqtoolOC();
            oaryC.setTool_stat(status);
            oaryC.setTime(time);
            oaryC.setTotalTime(wholeTime);
            oaryCList.add(oaryC);
        }
        return oaryCList;
    }


    //5天的公式分布，稼动率
    public void fiveDayStatus(FipinqtoolI inTrx,FipinqtoolO outTrx){
        Date nowDate = new Date();
        List<FipinqtoolOB> oaryBList = new ArrayList<>();
        List<FipinqtoolOC> oaryCList = new ArrayList<>();
        //日期 +  状态和时间
        Map<String,List<FipinqtoolOC>> newMap = new HashMap<>();
        //稼动率 RUN/所有工时
        for(int i = 1; i < 6 ;i++){
            Date dateBefore = Util.getDateBefore(nowDate,i);
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            String dateBefores = format.format(dateBefore);
            String fromdateString  = dateBefores + " 00:00:00";
            String todateString = dateBefores + " 24:00:00";
            Timestamp fromdateTimestamp = Timestamp.valueOf(fromdateString);
            Timestamp todateTimestamp = Timestamp.valueOf(todateString);
            List<FipinqtoolIA> iaryList = new ArrayList<>();
            FipinqtoolIA iary = new FipinqtoolIA();
            iary.setFrom_date(fromdateTimestamp);
            iary.setTo_date(todateTimestamp);
            iaryList.add(iary);
            inTrx.setIary(iaryList);

            oaryBList = getToolDiffStatePeriod(inTrx);
            if(oaryBList != null && oaryBList.size() > 0){
                oaryCList = makeOaryC(oaryBList);
                newMap.put(dateBefores,oaryCList);
            }
            System.out.println(dateBefores);
        }

        List<FipinqtoolOD> oaryDList = new ArrayList<>();
        Iterator iter = newMap.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next(); // 把hashmap转成Iterator再迭代到entry
            Object key = entry.getKey(); // 从entry获取key 设备ID
            Object val = entry.getValue(); // 从entry获取value 设备状态和时间

            String date = (String)key;
            List<FipinqtoolOC> oaryClist = (List<FipinqtoolOC>)val;
            FipinqtoolOD  oaryD = new FipinqtoolOD();
            oaryD.setDate(date);
            //状态比率
            Map<String,Double> toolStatusRate = new HashMap<>();
            for(int i = 0 ; i < oaryClist.size(); i++){
                //各个状态的比率
                String toolStat = oaryCList.get(i).getTool_stat();
                Long time = oaryCList.get(i).getTime();
                Long totaltime = oaryCList.get(i).getTotalTime();
                double statusRate = time * 1.0 / totaltime;
                DecimalFormat df = new DecimalFormat("#.00");
                toolStatusRate.put(toolStat,Double.valueOf(df.format(statusRate)));
                //算稼动率
                if(oaryCList.get(i).getTool_stat().equals("RUN")){
                    Long runTime = oaryCList.get(i).getTime();
                    Long totalTime  = oaryCList.get(i).getTotalTime();
                    double cropMobility = runTime * 1.0 / totalTime;
                    oaryD.setCrop_mobility(Double.valueOf(df.format(cropMobility)));
                }

            }
            oaryD.setToolStatusRate(toolStatusRate);
            oaryDList.add(oaryD);
        }
        outTrx.setOaryD(oaryDList);
        outTrx.setOaryB(oaryBList);
        outTrx.setOaryC(oaryCList);
        outTrx.setRtn_code(RETURN_CODE_OK);
        outTrx.setRtn_mesg(RETURN_MESG_OK);


    }


    private void getHisToolByCondition(HiptolhisI inTrx, HiptolhisO outTrx) {
        HiptolhisIA iary = inTrx.getIary().get(0);
//        Session session = sessionFactoryHis.openSession();
//		String toolHis_hql = "From His_ret_tool_st where tool_id_fk = '"+iary.getTool_id()+"' and evt_cate <> '"+EVT_TOOL_FETCH+"'";
		String toolHis_hql = "From His_ret_tool_st where tool_id_fk = '"+iary.getTool_id()+"'";
//		List<His_ret_tool_st> his_ret_tool_sts = session.createQuery(toolHis_hql).list();
		List<His_ret_tool_st> his_ret_tool_sts = hisRetToolStDao.find(toolHis_hql);
		List<HiptolhisOA> toolHisList = new ArrayList<HiptolhisOA>();
		for (His_ret_tool_st his_ret_tool_st : his_ret_tool_sts){
//		His_ret_tool_st his_ret_tool_st = his_ret_tool_sts.get(0);
				HiptolhisOA oaryA = new HiptolhisOA();
				oaryA.setTool_id_fk(his_ret_tool_st.getTool_id_fk());
				oaryA.setTool_stat(his_ret_tool_st.getTool_stat());
				oaryA.setTool_id_fk(his_ret_tool_st.getTool_id_fk());
				oaryA.setTool_stat(his_ret_tool_st.getTool_stat());
				oaryA.setTool_sub_stat(his_ret_tool_st.getTool_sub_stat());
				oaryA.setTool_lock_flg(his_ret_tool_st.getTool_lock_flg());
				oaryA.setTool_hold_flg(his_ret_tool_st.getTool_hold_flg());
				oaryA.setTool_run_mode(his_ret_tool_st.getTool_run_mode());
				oaryA.setLd_rtd_flg(his_ret_tool_st.getLd_rtd_flg());
				oaryA.setUl_rtd_flg(his_ret_tool_st.getUl_rtd_flg());
				oaryA.setPv_tool_stat(his_ret_tool_st.getPv_tool_stat());
				oaryA.setPv_tool_sub_stat(his_ret_tool_st.getPv_tool_sub_stat());
				oaryA.setTool_note(his_ret_tool_st.getTool_note());
				oaryA.setEvt_timestamp(his_ret_tool_st.getEvt_timestamp().toString());
				if(null != his_ret_tool_st.getClm_timestamp()){
					oaryA.setClm_timestamp(his_ret_tool_st.getClm_timestamp().toString());
				}
				if(null != his_ret_tool_st.getKeep_time()){
					oaryA.setKeep_time(his_ret_tool_st.getKeep_time().toString());
				}
				if(null != his_ret_tool_st.getUl_last_fetch_timestamp()){
					oaryA.setUl_last_fetch_timestamp(his_ret_tool_st.getUl_last_fetch_timestamp().toString());
				}
				if(null != his_ret_tool_st.getLd_last_fetch_timestamp()){
					oaryA.setLd_last_fetch_timestamp(his_ret_tool_st.getLd_last_fetch_timestamp().toString());
				}
				oaryA.setEvt_usr(his_ret_tool_st.getEvt_usr());
				toolHisList.add(oaryA);
		}

//		session.close();
        outTrx.setOary(toolHisList);
//		outTrx.setOaryB(ptHisList);
		outTrx.setRtn_code(RETURN_CODE_OK);
        outTrx.setRtn_mesg(RETURN_MESG_OK);
    }

}
